"""
文件上传工具
"""
import os
import uuid
from typing import Optional
from pathlib import Path
from fastapi import UploadFile, HTTPException
from PIL import Image

from app.config import settings


def get_file_extension(filename: str) -> str:
    """获取文件扩展名"""
    return filename.rsplit('.', 1)[-1].lower() if '.' in filename else ''


def generate_unique_filename(original_filename: str) -> str:
    """生成唯一文件名"""
    ext = get_file_extension(original_filename)
    unique_name = f"{uuid.uuid4().hex}.{ext}"
    return unique_name


async def save_upload_file(
    file: UploadFile,
    upload_dir: str = settings.UPLOAD_DIR,
    allowed_types: Optional[list] = None,
    max_size: Optional[int] = None
) -> str:
    """
    保存上传的文件
    
    Args:
        file: 上传的文件
        upload_dir: 上传目录
        allowed_types: 允许的文件类型
        max_size: 最大文件大小（字节）
    
    Returns:
        文件的相对路径
    """
    # 检查文件类型
    ext = get_file_extension(file.filename)
    if allowed_types and ext not in allowed_types:
        raise HTTPException(status_code=400, detail=f"不支持的文件类型: {ext}")
    
    # 读取文件内容
    content = await file.read()
    
    # 检查文件大小
    if max_size and len(content) > max_size:
        raise HTTPException(status_code=400, detail=f"文件大小超过限制")
    
    # 创建上传目录
    Path(upload_dir).mkdir(parents=True, exist_ok=True)
    
    # 生成唯一文件名
    filename = generate_unique_filename(file.filename)
    file_path = os.path.join(upload_dir, filename)
    
    # 保存文件
    with open(file_path, 'wb') as f:
        f.write(content)
    
    # 返回相对路径
    relative_path = file_path.replace('\\', '/')
    return f"/{relative_path}"


async def save_image(
    file: UploadFile,
    max_width: Optional[int] = None,
    max_height: Optional[int] = None
) -> str:
    """
    保存图片并可选压缩
    
    Args:
        file: 上传的图片
        max_width: 最大宽度
        max_height: 最大高度
    
    Returns:
        图片的相对路径
    """
    # 保存原始文件
    image_path = await save_upload_file(
        file,
        upload_dir=os.path.join(settings.UPLOAD_DIR, 'images'),
        allowed_types=settings.ALLOWED_IMAGE_TYPES,
        max_size=settings.MAX_UPLOAD_SIZE
    )
    
    # 如果需要压缩
    if max_width or max_height:
        full_path = image_path.lstrip('/')
        img = Image.open(full_path)
        
        # 计算新尺寸
        width, height = img.size
        if max_width and width > max_width:
            height = int(height * max_width / width)
            width = max_width
        if max_height and height > max_height:
            width = int(width * max_height / height)
            height = max_height
        
        # 调整大小
        if width != img.size[0] or height != img.size[1]:
            img = img.resize((width, height), Image.Resampling.LANCZOS)
            img.save(full_path, quality=85, optimize=True)
    
    return image_path


def delete_file(file_path: str) -> bool:
    """
    删除文件
    
    Args:
        file_path: 文件路径（相对路径）
    
    Returns:
        是否成功删除
    """
    try:
        full_path = file_path.lstrip('/')
        if os.path.exists(full_path):
            os.remove(full_path)
            return True
        return False
    except Exception:
        return False

